//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using OpenLS.Chart;
using OpenLS.Chart.UI;
using OpenLS.Drawing;
using OpenLS.Spreadsheet.Chart;
using OpenLS.Spreadsheet.Drawing;
using OpenLS.UI;
using Marker = OpenLS.Chart.Marker;

//\\using Microsoft.Win32;

namespace OpenLS.Spreadsheet.UI
{
    internal partial class WorksheetCharting
    {
        internal static void EnableCommands(UIElement g)
        {
            g.CommandBindings.Add(new CommandBinding(SpreadsheetCommands.InsertChart,
                                                     onInsertChart,
                                                     onCanInsertObject));
//            g.CommandBindings.Add(new CommandBinding(SpreadsheetCommands.insertPieChart,
            //              OnInsertPieChart, WorksheetGrid.OnHasSelection));
            g.CommandBindings.Add(new CommandBinding(SpreadsheetCommands.InsertPicture,
                                                     onInsertPicture, onCanInsertObject));
        }

        private static void onCanInsertObject(object sender, CanExecuteRoutedEventArgs args)
        {
           Worksheet worksheet = (Worksheet) SpreadsheetElement.GetWorksheet(sender);
            args.CanExecute = !worksheet.IsProtected(p => p.Objects);
            
            args.Handled = true;
        }

        private static void onInsertPicture(object sender, ExecutedRoutedEventArgs args)
        {
            Worksheet worksheet = getWorksheet(sender);
            var d = new OpenFileDialog
                        {
                            RestoreDirectory = true,
                            InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
                        };
            const string allExtensions =
                @"*.emf; *.wmf; *.jpg; *.jpeg; *.jfif; *.jpe; *.png; *.bmp; *.dib; *.rle; *bmz; *.gif, *.gfa, *.emz; *.wmz; *.pcz; *.tif; *.tiff; *.cdr; *.cgm; *.eps; *.pct; *.pict; *.wpg";
            d.DefaultExt = allExtensions;
            d.Filter = "All Pictures|" + allExtensions;

            if (d.ShowDialog(WindowServices.GetAncestor<Window>(sender)).GetValueOrDefault())
            {
                using (Stream stream = d.OpenFile())
                {
                    string fn = Path.GetFileNameWithoutExtension(d.FileName);

                    var picture =
                        new Picture(
                            BitmapDecoder.Create(stream, BitmapCreateOptions.PreservePixelFormat,
                                                 BitmapCacheOption.OnLoad).Frames[0]);
                    string goodName = fn;
                    for (int i = 0; i < 1000000; i++)
                    {
                        bool found = false;
                        foreach (Anchor anchor in worksheet.Anchors)
                            if (anchor.Content is Picture)
                            {
                                var p = (Picture) anchor.Content;
                                if (p.Name == goodName)
                                {
                                    found = true;
                                    break;
                                }
                            }
                        if (!found)
                            break;
                        goodName = fn + i;
                    }
                    picture.Name = goodName;
                    picture.NavigationId = worksheet.Anchors.Count + 1;

                    picture.Stretch = Stretch.Fill;
                    var a = new OneCellAnchor(worksheet)
                                {
                                    Content = picture,
                                    Width = picture.Source.Width,
                                    Height = picture.Source.Height
                                };
                    //\\drawing.Anchors.Add(a);
                    worksheet.Anchors.Add(a);
                }
            }
        }

        private static Worksheet getWorksheet(object sender)
        {
            return WorksheetHelper.GetWorksheet(sender);
        }

        private static void onInsertChart(object sender, ExecutedRoutedEventArgs args)
        {
            object p = args.Parameter ?? new ColumnChartTemplate();
            if (p is Column3DChartTemplate)
            {
                var t = (Column3DChartTemplate) p;
                insertAnyBar3DChart(getWorksheet(sender), BarDirection.Column, t.Grouping, t.Shape);
                return;
            }
            if (p is ColumnChartTemplate)
            {
                var t = (ColumnChartTemplate) p;
                insertAnyBarChart(getWorksheet(sender), BarDirection.Column, t.Grouping);
                return;
            }
            if (p is LineChartTemplate)
            {
                var t = (LineChartTemplate) p;
                insertLineChart(getWorksheet(sender), t.Grouping, t.Marker);
                return;
            }
            if (p is Line3DChartTemplate)
            {
                insertLine3DChart(getWorksheet(sender));
                return;
            }
            if (p is Bar3DChartTemplate)
            {
                var t = (Bar3DChartTemplate) p;
                insertAnyBar3DChart(getWorksheet(sender), BarDirection.Bar, t.Grouping, t.Shape);
                return;
            }
            if (p is BarChartTemplate)
            {
                var t = (BarChartTemplate) p;
                insertAnyBarChart(getWorksheet(sender), BarDirection.Bar, t.Grouping);
                return;
            }
            if (p is Area3DChartTemplate)
            {
                var t = (Area3DChartTemplate) p;
                insertArea3DChart(getWorksheet(sender), t.Grouping); //\\
                return;
            }
            if (p is AreaChartTemplate)
            {
                var t = (AreaChartTemplate) p;
                insertAreaChart(getWorksheet(sender), t.Grouping);
                return;
            }
            if (p is PieChartTemplate)
            {
                var t = (PieChartTemplate) p;
                insertPieChart(getWorksheet(sender), t.IsExploded);
                return;
            }
            if (p is Pie3DChartTemplate)
            {
                var t = (Pie3DChartTemplate) p;
                insertPie3DChart(getWorksheet(sender), t.IsExploded);
                return;
            }
            if (p is ScatterChartTemplate)
            {
                var t = (ScatterChartTemplate) p;
                insertScatterChart(getWorksheet(sender), t);
                return;
            }
            throw new NotSupportedException();
        }

        private static void insertScatterChart(Worksheet worksheet, ScatterChartTemplate t)
        {
            var chartSpace = new ChartArea();
            var plotArea = new PlotArea();
            chartSpace.PlotArea = plotArea;
            var chart = new ScatterChart();
            if (t.IsSmooth)
                chart.ScatterStyle = ScatterStyle.SmoothMarker;
            // barChart.Theme = Worksheet.Workbook;
            plotArea.Axes.Add(chart.VerticalAxis);
            plotArea.Axes.Add(chart.HorizontalAxis);
            plotArea.Charts.Add(chart);
            int index = 0;
            chartSpace.Legend = new Legend(chartSpace);
            var slicer = new Slicer(worksheet.Selection);
            chart.VaryColors = slicer.ReferenceCount <= 1;
            RangeNumericReference reference = null;
            foreach (RangeNumericReference nr in slicer.GetValueReferences())
            {
                var series = new ScatterSeries {Index = index, Order = index, IsSmooth = t.IsSmooth};
                if (t.NoLine)
                    series.ShapeProperties = new ShapeProperties
                                                 {
                                                     LineProperties =
                                                         new LineProperties
                                                             {LineFillProperties = new NoFillProperties()}
                                                 };
                // var nr = new RangeNumericReference();
                // nr.SetRange(range);
                if (reference == null)
                {
                    reference = nr;
                    continue;
                }
                //series. = nr;
                series.XValues = reference;
                series.YValues = nr;
                if (!t.HasMarkers)
                {
                    series.Marker = new Marker {Symbol = MarkerStyle.None};
                }
                chart.Series.Add(series);
                index++;
            }
            AddChartSpace(worksheet, chartSpace);
        }

        private static void insertPie3DChart(Worksheet worksheet, bool hasexplosion)
        {
            int explosion = 0;
            if (hasexplosion)
                explosion = 1;
            var chartSpace = new ChartArea();
            var plotArea = new PlotArea();
            chartSpace.PlotArea = plotArea;
            var pieChart = new Pie3DChart();
            // pieChart.Theme = worksheet.Workbook;
            plotArea.Charts.Add(pieChart);
            chartSpace.Legend = new Legend(chartSpace);
            var slicer = new Slicer(worksheet);
            foreach (
                PieSeries series in
                    slicer.GetValueSeries(
                        (nr, ds) => new PieSeries {Explosion = explosion, Values = nr, Categories = ds}))
            {
                pieChart.Series.Add(series);
            }
            foreach (LegendEntry legendEntry in slicer.GetLegendEntries())
            {
                chartSpace.Legend.Entries.Add(legendEntry);
            }
            AddChartSpace(worksheet, chartSpace);
        }

        private static void insertPieChart(Worksheet worksheet, bool hasexplosion)
        {
            int explosion = 0;
            if (hasexplosion)
                explosion = 1;
            var plotArea = new PlotArea();
            var chartSpace = new ChartArea();
            chartSpace.PlotArea = plotArea;
            var pieChart = new PieChart();
            // pieChart.Theme = Worksheet.Workbook;
            plotArea.Charts.Add(pieChart);
            chartSpace.Legend = new Legend(chartSpace);
            var slicer = new Slicer(worksheet);
            foreach (
                PieSeries series in
                    slicer.GetValueSeries(
                        (nr, ds) => new PieSeries {Explosion = explosion, Values = nr, Categories = ds}))
            {
                pieChart.Series.Add(series);
            }
            foreach (LegendEntry legend in slicer.GetLegendEntries())
            {
                chartSpace.Legend.Entries.Add(legend);
            }
            AddChartSpace(worksheet, chartSpace);
        }

        private static void AddChartSpace(Worksheet worksheet, ChartArea chartSpace)
        {
            var f = new GraphicFrame {Id = 1, Name = "mychart"};
            var g = new Graphic();
            f.Graphic = g;
            g.ChartSpace = chartSpace;
            TwoCellAnchor a = createAnchor(worksheet, f);
            worksheet.Anchors.Add(a);
        }

        private static void insertLine3DChart(Worksheet worksheet)
        {
            var chartSpace = new ChartArea();
            var plotArea = new PlotArea();
            chartSpace.PlotArea = plotArea;
            var barChart = new Line3DChart();
            // barChart.Theme = worksheet.Workbook;
            plotArea.Axes.Add(barChart.FirstAxis);
            plotArea.Axes.Add(barChart.SecondAxis);
            plotArea.Charts.Add(barChart);
            chartSpace.Legend = new Legend(chartSpace);
            var slicer = new Slicer(worksheet);
            barChart.VaryColors = slicer.ReferenceCount <= 1;
            foreach (
                LineSeries series in slicer.GetValueSeries((nr, ds) => new LineSeries {Values = nr, Categories = ds}))
            {
                barChart.Series.Add(series);
            }
            AddChartSpace(worksheet, chartSpace);
        }

        private static Type uniformTypeOf(Range range)
        {
            Type result = null;
            foreach (Cell cell in Enumerable.Where(range.GetNonEmptyCells(), c => c.Value != null))
            {
                Type t = cell.Value.GetType();
                if (result == null)
                {
                    result = t;
                    continue;
                }
                if (result != t)
                    return null;
            }
            return result;
        }

        private static void insertArea3DChart(Worksheet worksheet, Grouping grouping)
        {
            var chartSpace = new ChartArea();
            var plotArea = new PlotArea();
            chartSpace.PlotArea = plotArea;
            var axis1 = new CategoryAxis {Position = AxisPosition.Bottom};
            var axis2 = new ValueAxis {Position = AxisPosition.Left};
            axis1.Position = AxisPosition.Bottom;
            var areaChart = new Area3DChart();
            //areaChart.Theme = worksheet.Workbook;
            plotArea.Axes.Add(axis1);
            axis1.CrossAxis = axis2;
            axis2.CrossAxis = axis1;
            plotArea.Axes.Add(axis2);
            plotArea.Charts.Add(areaChart);
            areaChart.Grouping = grouping;
            chartSpace.Legend = new Legend(chartSpace);
            var slicer = new Slicer(worksheet);

            foreach (AreaSeries series in slicer.GetValueSeries((nr, ds) => new AreaSeries {Values = nr}))
            {
                //\\  if (uniformTypeOf(range) != typeof(double))
                //\\  {
                //\\      new RangeStringReference(range);

                //\\      continue;
                //\\  }

                areaChart.Series.Add(series);
            }
            foreach (LegendEntry legendEntry in slicer.GetLegendEntries())
            {
                chartSpace.Legend.Entries.Add(legendEntry);
            }
            AddChartSpace(worksheet, chartSpace);
        }

        private static void insertAreaChart(Worksheet worksheet, Grouping grouping)
        {
            var chartSpace = new ChartArea();
            var plotArea = new PlotArea();
            chartSpace.PlotArea = plotArea;
            var axis1 = new CategoryAxis {Position = AxisPosition.Bottom};
            axis1.Position = AxisPosition.Bottom;
            var axis2 = new ValueAxis {Position = AxisPosition.Left};
            axis1.Position = AxisPosition.Bottom;
            var areaChart = new AreaChart(axis1, axis2);
            //areaChart.Theme = worksheet.Workbook;
            plotArea.Axes.Add(axis1);
            axis1.CrossAxis = axis2;
            axis2.CrossAxis = axis1;
            plotArea.Axes.Add(axis2);
            plotArea.Charts.Add(areaChart);
            areaChart.Grouping = grouping;
            chartSpace.Legend = new Legend(chartSpace);
            var slicer = new Slicer(worksheet);

            foreach (AreaSeries series in slicer.GetValueSeries((nr, ds) => new AreaSeries {Values = nr, Categories = ds}))
            {
                if (false) //\\uniformTypeOf(range) != typeof(double))
                {
                    //\\new RangeStringReference(range);

                    //\\continue;
                }
                areaChart.Series.Add(series);
            }
            foreach (LegendEntry legendEntry in slicer.GetLegendEntries())
            {
                chartSpace.Legend.Entries.Add(legendEntry);
            }
            AddChartSpace(worksheet, chartSpace);
        }

        private static void insertLineChart(Worksheet worksheet, Grouping grouping, bool marker)
        {
            var chartSpace = new ChartArea();
            var plotArea = new PlotArea();
            chartSpace.PlotArea = plotArea;
            var lineChart = new LineChart {Marker = marker};
            //  lineChart.Theme = Worksheet.Workbook;
            plotArea.Axes.Add(lineChart.VerticalAxis);
            plotArea.Axes.Add(lineChart.HorizontalAxis);
            plotArea.Charts.Add(lineChart);
            lineChart.Grouping = grouping;
            chartSpace.Legend = new Legend(chartSpace);
            var slicer = new Slicer(worksheet);
            foreach (
                LineSeries series in slicer.GetValueSeries((nr, ds) => new LineSeries {Values = nr, Categories = ds}))
            {
                if (!marker)
                    series.Marker = new Marker {Symbol = MarkerStyle.None};
                lineChart.Series.Add(series);
            }
            foreach (LegendEntry legendEntry in slicer.GetLegendEntries())
            {
                chartSpace.Legend.Entries.Add(legendEntry);
            }
            AddChartSpace(worksheet, chartSpace);
        }

        private static TwoCellAnchor createAnchor(Worksheet worksheet, GraphicFrame f)
        {
            return new TwoCellAnchor(worksheet)
                       {
                           Content = f,
                           Cell = new CellAddress(worksheet.ActivePane.Top + 4, worksheet.ActivePane.Left + 1),
                           SecondCell = new CellAddress(12, 12),
                           ActualWidth = 500,
                           ActualHeight = 300
                       };
        }

        private static void insertAnyBarChart(Worksheet worksheet, BarDirection barDirection, BarGrouping barGrouping)
        {
            var chartSpace = new ChartArea();
            var plotArea = new PlotArea();
            chartSpace.PlotArea = plotArea;
            var barChart = new BarChart();
            // barChart.Theme = worksheet.Workbook;
            plotArea.Axes.Add(barChart.CategoryAxis);
            plotArea.Axes.Add(barChart.ValueAxis);
            plotArea.Charts.Add(barChart);
            barChart.Direction = barDirection;
            barChart.Grouping = barGrouping;
            chartSpace.Legend = new Legend(chartSpace);
            barChart.VaryColors = false;
            var slicer = new Slicer(worksheet);
            foreach (BarSeries series in slicer.GetValueSeries((nr, ds) => new BarSeries {Values = nr, Categories = ds})
                )
            {
                barChart.Series.Add(series);
            }
            foreach (LegendEntry legendEntry in slicer.GetLegendEntries())
            {
                chartSpace.Legend.Entries.Add(legendEntry);
            }
            AddChartSpace(worksheet, chartSpace);
        }

        private static void insertAnyBar3DChart(Worksheet worksheet, BarDirection barDirection, BarGrouping barGrouping,
                                                ChartShape shape)
        {
            var chartSpace = new ChartArea();
            var plotArea = new PlotArea();
            chartSpace.PlotArea = plotArea;
            var barChart = new Bar3DChart();
            chartSpace.View3D = new View3D();
            barChart.Shape = shape;
            // barChart.Theme = worksheet.Workbook;
            plotArea.Axes.Add(barChart.CategoryAxis);
            plotArea.Axes.Add(barChart.ValueAxis);
            plotArea.Charts.Add(barChart);
            barChart.Direction = barDirection;
            barChart.Grouping = barGrouping;
            chartSpace.Legend = new Legend(chartSpace);
            var slicer = new Slicer(worksheet);

            barChart.VaryColors = false; //= new List<Range>(getSlicedRanges(worksheet.Selection)).Count <= 1;
            foreach (BarSeries series in slicer.GetValueSeries((nr, ds) => new BarSeries {Values = nr, Categories = ds})
                )
            {
                barChart.Series.Add(series);
            }
            AddChartSpace(worksheet, chartSpace);
        }
    }
}